/*
 * @Descripttion: 添加金牌话术推送事件
 * @Author: yansu
 * @Date: 2020-10-28 15:56:12
 * @LastEditors: yansu
 * @LastEditTime: 2020-11-24 18:59:09
 */
/**
 * Created by zengyx on 16/12/19.
 */
// import io from 'socket.io-client'
import * as types from './mutation-types'
import * as gtypes from '../../mutation-types'
import * as customerTypes from '../../modules/customer/mutation-types'
import * as webchatTypes from '../../modules/webchat/mutation-types'
import * as emailType from '../../modules/email/mutation-types'
import * as ctiType from '../../modules/cti/mutation-types'
import * as callType from '../../modules/call/mutation-types'
import * as orderType from '../../modules/order/mutation-types'
import * as busType from '../business/mutation-types'
import { deepClone, aesEncrypt, m7Language } from '@/utils/m7Utils.js'
import { refreshCache } from '@/utils/refreshCache.js'
import * as monitor from '../monitor/actions'
import * as cti from '../cti/actions'
import { Base64 } from 'js-base64'
import { Message } from 'element-ui'
import common from '../../api/common'
import login from '../../api/login'
import bus from '../../eventBus'
let md5 = require('md5')
let socket = null
let reconnectCount = 0
let socketConnect = false
const state = {
  lastSocketId: null,
  token: ''
}
function isMD5 (str) {
  let md5 = /^[a-f0-9]{32}$/
  return md5.test(str)
}
function socketPromise (res) {
  return new Promise((resolve, reject) => {
    let newScript = document.createElement('script')
    let head = document.getElementById('topHead')
    if (res && res.data && res.data.clientVersion === '2.4.0') {
      newScript.src = '/static/js/socket.io-2.4.0.js'
    } else {
      newScript.src = '/static/js/socket.io-1.7.3.js'
    }
    newScript.async = 'async'
    head.insertBefore(newScript, head.firstChild)
    newScript.onload = newScript.onreadystatechange = function () {
      if (!this.readyState || this.readyState === 'loaded'|| this.readyState === 'complete') {
        resolve(res)
      }
      newScript.onload = newScript.onreadystatechange = null
    }
  }).catch((reject) => {
    reject(res)
  })
}

export default {
  state,
  actions: {
    initSocket: ({commit, state, rootState, dispatch}, versionData) => {
      let socketPushUrl = rootState.pushServerUrl
      if (versionData && versionData.data) {
        socketPushUrl = versionData.data.server || rootState.pushServerUrl
      }
      let pwd = rootState.session.user.password
      let token = md5(state.token + '_&_' + rootState.session.user.exten + '_&_' + rootState.session.user.account)
      if (!isMD5(pwd)) {
        pwd = md5(token + md5(pwd))
      }
      let userInfo = {
        username: rootState.session.user.exten,
        password: pwd,
        account: rootState.session.user.account
      }
      let base64Data = Base64.encode(JSON.stringify(userInfo))
      let encryptData = aesEncrypt(base64Data)
      let query = {
        encryptData: encryptData,
        token: token
      }
      reconnectCount = 0
      console.log(io, 'io===========')
      socket = io.connect(socketPushUrl, {
        'force new connection': true,
        reconnectionDelay: 3000,
        query: query
      })

      socket.on('disconnect', () => { // 断开连接
        Message({ message: m7Language('public.socketError'), type: 'error', duration: 0 })
        let data = {
          type: 'webchat_websocket_disconnect',
          account: rootState.session.user.account || '',
          username: rootState.session.user.exten || ''
        }
        dispatch('collectEventLog', data)
      })

      socket.on('connect_failed', () => { // 连接失败
        Message({ message: m7Language('public.socketError'), type: 'error', duration: 0 })
        let data = {
          type: 'webchat_websocket_connect_failed',
          account: rootState.session.user.account || '',
          username: rootState.session.user.exten || ''
        }
        dispatch('collectEventLog', data)
      })

      socket.on('reconnect_failed', () => { // 重连失败
        Message({ message: m7Language('public.socketError'), type: 'error', duration: 0 })
        let data = {
          type: 'webchat_websocket_reconnect_failed',
          account: rootState.session.user.account || '',
          username: rootState.session.user.exten || ''
        }
        dispatch('collectEventLog', data)
      })

      socket.on('connect_error', function () {
        console.log('connect_error')
        reconnectCount = reconnectCount + 1
        if (reconnectCount > 3) {
          dispatch('getSocketPushServiceAddress')
          // 重连超过3次失败上传记录
          if (state.lastSocketId !== null) {
            let data = {
              type: 'webchat_websocket_reconnect_error',
              account: rootState.session.user.account || '',
              username: rootState.session.user.exten || ''
            }
            dispatch('collectEventLog', data)
          }
        }
      })

      socket.on('connect', function (data) {
        console.log('connnect websocket success')
        socketConnect = true
        // 掉线自动登录后的处理,去判断在线客服是否存在窗口,然后去获取离线消息展示
        if (state.lastSocketId !== null) {
          dispatch('processAutoOnlineAfterOffline')
          dispatch('refreshNoticeUndealNum1')
          Message.closeAll()
        }
      })

      socket.on('error', function (data) { // 错误发生，并且无法被其他事件类型所处理
        console.log('push connection error' + JSON.stringify(data))
        Message({ message: m7Language('public.socketError'), type: 'error', duration: 0 })
        let obj = {
          type: 'webchat_websocket_reconnect_failed',
          account: rootState.session.user.account || '',
          username: rootState.session.user.exten || '',
          data
        }
        dispatch('collectEventLog', obj)
      })
      socket.on('socketId', function (socketData) {
        commit(types.UPDATE_SOCKET_PUSH_TOKEN, {token: socketData.token})
        let token = md5(state.token + '_&_' + rootState.session.user.exten + '_&_' + rootState.session.user.account)
        let password = md5(token + md5(rootState.session.user.password))
        let userInfo = {
          username: rootState.session.user.exten,
          password: password,
          account: rootState.session.user.account
        }
        let base64Data = Base64.encode(JSON.stringify(userInfo))
        let encryptData = aesEncrypt(base64Data)
        socket.io.opts.query = 'encryptData=' + encryptData + '&token=' + token
        let socketId = socketData.socketId

        // let port = socketData.port;
        // let ip = socketData.ip;
        // do something...
        // 如建立跟后端服务的联系，他们之间可以用session维系
        // 后端可以维护这样的关系：{socketId:socketId, ip: ip, port:port, session:session}，
        // 后端服务就可以根据session找寻socketId, ip, port
        // 掉线了,记住上一次用户的选择
        if (state.lastSocketId !== null) {
          // dispatch('updateWebchatAutoClaimStatus', {status: rootState.webchat.isOn})
          // 更新离线后上线邮件领取状态
          // dispatch('updateEmailAutoClaimStatus', {emailStatus: rootState.email.isOn})
          socketData.chatStatus = rootState.webchat.isOn
          if (rootState.email.isOn) {
            socketData.emailStatus = 'open'
          } else {
            socketData.emailStatus = 'close'
          }
          // socketData.lastSocketId = state.lastSocketId
        } else {
          if (rootState.session.user.imClaimStatus === 'close') {
            commit(webchatTypes.SET_WEBCHAT_AUTOCLAIM, {status: 'close'})
          }
          if (rootState.session.user.emailClaimStatus === 'open') {
            // 邮件会话领取开关的状态，用的是true和false
            commit(emailType.SET_EMAIL_AUTOCLAIM, {emailStatus: true})
          }
        }
        if (window.sessionStorage.getItem('webChatIsOn')) {
          socketData.chatStatus = window.sessionStorage.getItem('webChatIsOn')
          commit(webchatTypes.SET_WEBCHAT_AUTOCLAIM, {status: socketData.chatStatus})
        }
        if (window.sessionStorage.getItem('webStatusConfig')) {
          socketData.chatStatusDetail = JSON.parse(window.sessionStorage.getItem('webStatusConfig')).webStatusId
        }
        if (rootState.session.user.uversion && rootState.session.user.uversion === 'monitor') {
          socketData.emailStatus = 'close'
          socketData.chatStatus = 'close'
        }
        commit(types.UPDATE_SOCKETID, {socketId: socketId})

        dispatch('pushSocketLogined', socketData)
      })
      socket.on('pushMsg', function (data, fn) {
        // 回给服务器进行确认
        if (fn && typeof fn === 'function') {
          fn('success')
        }
        // todo
        // 这里是服务端接收到的事件，根据事件类型进行不同处理
        if (data.Event === 'refreshCache') {
          // 刷新缓存的事件
          refreshCache(data.Data || {}, dispatch)
        } else if (data.Event === 'notice') {
          cti.noticeEventProcess({ commit, state, rootState, dispatch }, data)
          let param = data.Data || {}
          let notify = {
            content: param.content,
            title: param.title
          }
          commit(gtypes.SET_NOTIFY, { tag: 'notice', notify: notify })
        } else if (data.Event === 'autoqc') {
          cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
          let param = data.Data || {}
          let notify = {
            _id: param.id,
            type: param.type
          }
          commit(gtypes.SET_NOTIFY, { tag: 'autoqc', notify: notify })
        } else if (data.Event === 'NewWebchat' || data.Event === 'BatchNewWebchat' || data.Event === 'GroupMsg' || data.Event === 'NewNotify' || data.Event === 'sendMsgResult' || data.Event === 'VoiceToText') {
          //  //do something...
          //  handler.webchat.dispatch(data);
          // 客户分配的通知在这里加
          if (data.Event === 'NewNotify' && data.Data && data.Data.type === 'newNotification') {
            let msg = data.Data.content || ''
            if (data.Data.emailType && data.Data.emailType === 'emailTimeout') {
              commit(gtypes.SET_NOTIFY, {tag: 'emailTimeOut', notify: {msg: msg, id: data.Data.emailSessionId}})
            } else if (data.Data.exportType) {
              commit(gtypes.SET_NOTIFY, {tag: 'exportType', notify: {msg: msg, type: data.Data.exportType, exportFlag: data.Data.exportFlag}})
            } else if (msg) {
              commit(gtypes.SET_NOTIFY, {tag: 'business', notify: {msg: msg, type: data.Data.businessType}})
            }
            cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
          } else if (data.Event === 'NewNotify' && data.Data && data.Data.type === 'configFlush') {
            if (data.Data.platform === 'dy') {
              bus.$emit('refreshDyAccessList', data.Data)
            } else if (data.Data.platform === 'wxkf') {
              bus.$emit('refreshWxkfAccessList', data.Data)
            } else if (data.Data.platform === 'wxwork') {
              bus.$emit('refreshWxworkAccessList', data.Data)
            }
          } else if (data.Event === 'NewNotify' && data.Data && data.Data.type === 'snsapiUserinfoUpdateSession') {
            bus.$emit('serHeaderImg', data.Data)
            commit(webchatTypes.UPDATE_IMAGE, {chatSessionId: data.Data.chatSessionId, headUrl: data.Data.headUrl, sName: data.Data.sName})
          } else {
            dispatch('dispatchWebchat', data)
          }
        } else if (data.Event === 'ImMonitor') {
          monitor.imMonitorEventProcess({commit, state, rootState, dispatch}, data)
        } else if (data.Event === 'MailMonitor') {
          if (rootState.monitor.moduleOpen.webchat) {
            monitor.mailMonitorEventProcess({commit, state, rootState, dispatch}, data)
          }
        } else if (data.Event === 'IvrSoundTransferNotify') {
          commit(gtypes.IVR_SOUND_TRANSFER, data)
        } else if (data.Event === 'NewEmail' || data.Event === 'NewEmailNotify' || data.Event === 'emailCSRInfo' || data.Event === 'NewEmailNotify') {
          dispatch('dispatchEmail', data)
          // } else if(data.Event == 'IvrSoundTransferNotify'){
          //  handler.config.callConfig.sound.uploadTransferSuccess(data);
          // } else if(data.Event == 'NewEmail' || data.Event == 'NewEmailNotify'){
          //  handler.email.dispatch(data);
          // } else if(data.Event == 'leakAssignMsg'){
          //  handler.cdr.dispatch(data.Data);
        } else if (data.Event === 'customerPlan') {
          let param = data.Data || {}
          console.log(param)
          let notify = {
            status: param.status,
            type: param.type,
            notifyTime: param.notifyTime,
            custName: param.custName,
            remark: param.remark,
            _id: param.cid
          }
          commit(gtypes.SET_NOTIFY, { tag: 'customerPlan', notify: notify })
          cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
        } else if (data.Event === 'quesNotify') {
          let param = data.Data || {}
          let notify = {
            notifyTime: param.notifyTime,
            _id: param.quesId
          }
          commit(gtypes.SET_NOTIFY, { tag: 'quesNotify', notify: notify })
          // var msg = '您有问卷定于' + param.notifyTime + '回访，请及时回访'
          // emitQuesNotify('您有一条问卷回访提醒', msg)
        } else if (data.Event === 'saleChance') {
          if (data.Data && data.Data.type === 'batchAssign') {
            cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
          }
          let notify = data.Data || {}
          let paths = rootState.route && rootState.route.fullPath ? rootState.route.fullPath.split('/') : []
          let type = paths[2]
          let tabType = paths[3]
          let cId = paths[4]
          commit(gtypes.SET_NOTIFY, { tag: 'saleChance', notify: notify })
          commit(customerTypes.REFRESH_LEFT)

          if (type === 'customer' && (tabType === 'customer_my' || tabType === 'customer_plan') && notify.type === 'updateOwner' && cId === notify.cid) {
            commit(customerTypes.EMPTY_RIGHT)
          }
        } else if (data.Event === 'business') {
          commit(busType.REFRESH_MENUBAR, Math.random()) // 刷新新版工单的左侧菜单栏数量统计
          let msg = data.Data.content || ''
          if (data.Data.type === 'businessUser') {
            // 与小铃铛通知重复
            return
          }
          commit(gtypes.SET_NOTIFY, {tag: 'business', notify: {msg: msg, type: data.Data.businessType}})
        } else if (data.Event === 'UbaNotify') {
          dispatch('dispatchUba', data)
        } else if (data.Event === 'leakAssignMsg') {
          commit(gtypes.SET_NOTIFY, {tag: 'leakAssignMsg', notify: {msg: data}})
        } else if (data.Event === 'RemoteAssistMonitor') {
          bus.$emit('RemoteAssistMonitorChange', data.Data)
        } else if (data.Event === 'riskControl') { // 风控
          commit(ctiType.RISK_DIALOG, true)
          commit(ctiType.RISK_DATA, data.Data || {})
        } else if (data.Event === 'callTranslation') { // 通话实时转写
          let datass = data.Data
          // commit(callType.SOCKET_TRANS, data.Data || {})
          commit(callType.SOCKET_TRANS, datass || {}, data)
        } else if (data.Event === 'offlineTrans') { // 通话离线转写
          commit(callType.SOCKET_OFFLINE_TRANS, data || '')
        } else if (data.Event === 'callSensitiveWords') {
          cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
          let param = data.Data || {}
          let notify = {
            content: param.content,
            title: param.title
          }
          commit(gtypes.SET_NOTIFY, { tag: 'callnotice', notify: notify })
        } else if (data.Event === 'monitorWarning') {
          cti.noticeEventProcess({commit, state, rootState, dispatch}, data)
          let param = data.Data || {}
          let content = ''
          if (param.type === 'agentBusyStatus') {
            dispatch('getCache', {type: 'phoneBars'}).then((res)=>{
              let details = param.details
              let state = details.status
              let content = ''
              res.some((item) => {
                if (item.PhoneBarItemId === state) {
                  content = param.agentName + '(' + param.agentExten + ')' + item.PhoneBarItemName + '状态已超时'
                  return true;
                }
              })
              let notify = {
                content: content,
                title: '监控告警通知'
              }
              commit(gtypes.SET_NOTIFY, { tag: 'callnotice', notify: notify })
            })
          } else {
            content = param.agentName + '(' + param.agentExten + ')' + '通话状态已超时'
            let notify = {
              content: content,
              title: '监控告警通知'
            }
            commit(gtypes.SET_NOTIFY, { tag: 'callnotice', notify: notify })
          }
        }else if(data.Event === 'callScriptRecommendation'){
          //金牌话术实时推荐列表
          if(data.Data.scripts.length){
            commit(callType.INTELLIGENT_RECOMMEND,data.Data.scripts)
          }
        }else if(data.Event == 'callScriptMatch'){
          commit(callType.INTELLIGENT_MATCH,data.Data)
        } else if (data.Event === 'businessMonitor') {
          // 工单监控数据实时推送
          commit(orderType.SET_ORDERMONITOR,data.Data)
        }
        const eventMap = new Map([
          ['NewNotify_webchat', { handle: gtypes.SET_TRANSFER_NOTICE, wsData: data.Data }],
          ['NewWebchat_webchat', { handle: gtypes.SET_TRANSFER_NO_CONFIRM_NOTICE, wsData: data.Data }]
        ])
        const { handle, wsData } = eventMap.get(`${data.Event}_${data.Data.type}`)
        if (handle && wsData) {
          commit(handle, wsData)
        }
        // 更多业务处理...
      })

      // 关闭事件时，调用socket的
      if (window.addEventListener) {
        window.addEventListener('close', function () {
          socket.disconnect()
        })
      } else {
        window.attachEvent('onclose', function () {
          socket.disconnect()
        })
      }
      // 连接不上socket加强提示
      setTimeout(() => {
        if (!socketConnect) {
          Message({ message: m7Language('public.socketError'), type: 'error', duration: 0, customClass: 'socketConnectLose' })
        }
      }, 30000)
    },
    refreshNoticeUndealNum1: ({commit, state, rootState, dispatch}) => {
      cti.refreshNoticeUndealNum({commit, state, rootState, dispatch})
    },
    processAutoOnlineAfterOffline: ({commit, state, rootState, dispatch}) => { // 断线重连后接收访客发送的信息
      let chatSessions = deepClone(rootState.webchat.webchatList.webchat_todo.list)
      let _processOfflineMessage = function (chatSessions, cb) {
        if (chatSessions.length === 0) {
          cb()
          return
        }
        let chatSession = chatSessions.pop()
        let currentMessageList = rootState.webchat.current.webchat_todo.messageList[chatSession._id]
        if (chatSession && chatSession._id && currentMessageList && currentMessageList.length > 0) {
          let query = {sessionId: chatSession._id, sid: chatSession.sid}
          let allInMsg = currentMessageList.filter((v, i) => {
            if (v.type === 'in' || v.type === 'system') {
              return v
            }
          })
          let when = allInMsg && allInMsg[allInMsg.length - 1] ? allInMsg[allInMsg.length - 1].when : ''
          if (when) {
            // query.when = parseInt(when)
            query.type = {$in: ['in', 'system']}
            query.submenu = 'webchat_todo'
            query.whenGt = parseInt(when)
            query.currentSessionId = chatSession._id
          }
          dispatch('queryMessageHistory', query).then((req) => { // 查询座席断线后访客发送的信息
            let msgList = deepClone(req)
            msgList = msgList.reverse()
            for (let i = 0; i < msgList.length; i++) {
              let msgItem = msgList[i]
              msgItem.content = msgItem.message
              msgItem.msgType = 'newMsg'
              let obj = rootState.webchat.webchatList.webchat_todo.list.filter(item => item._id === msgItem.sessionId)[0]
              if (obj) {
                msgItem.sName = obj.sName
              }
              msgItem._id = msgItem.sessionId
              if (msgItem.contentType !== 'video' && msgItem.contentType !== 'screenShare') {
                commit(gtypes.SET_NOTIFY, {tag: 'webchat', notify: msgItem}) // 推送浏览器消息
              }
            }
            _processOfflineMessage(chatSessions, cb)
          })
        } else {
          _processOfflineMessage(chatSessions, cb)
        }
      }
      _processOfflineMessage(chatSessions, function () {
        /**
         * 在这期间领取的新的会话也要刷进来
         */
        let data = {
          submenu: 'webchat_todo'
        }
        let currentList = deepClone(rootState.webchat.webchatList.webchat_todo.list)
        dispatch('queryWebchatList', data).then((req) => { // 查询会话列表
          if (req.success && req.list.length && req.list.length > currentList.length) {
            let newCurrList = req.list
            currentList.forEach((item, index) => {
              for (let i = 0; i < newCurrList.length; i++) { // 判断查询出的列表中是否有新接入的会话
                if (newCurrList[i]._id !== item._id) {
                  newCurrList[i].isNew = true
                } else {
                  newCurrList[i].isNew = false
                }
              }
            })
            if (!currentList.length) {
              newCurrList.forEach((item, index) => {
                item.isNew = true
              })
            }
            for (let i = 0; i < newCurrList.length; i++) {
              let data = newCurrList[i]
              if (data.isNew) {
                data.content = ''
                data.msgType = 'newConn'
                data.toUserName = data.sName
                commit(gtypes.SET_NOTIFY, {tag: 'webchat', notify: data})
                // dispatch('webchatTodoItemAdd', data)
              }
            }
          }
        })
      })
    },
    getSocketPushServiceAddress: ({commit, rootState, dispatch}) => {
      common.getSocketPushAddress({isSocket: true, accountId: rootState.session.user.account || ''})
        .then((result) => {
          if (result.success) {
            commit(types.PUSH_SOCKET_LOGIN, true)
            commit(gtypes.UPDATE_PUSH_URL, result)

            socket.disconnect()
            socket = null
            reconnectCount = null
            dispatch('initSocket', {})
          }
        }).catch(err => {
          console.log(err)
          // 'message.default_tips'
        })
    },
    getSocketVersion: ({commit, dispatch}, data) => {
      return common.getSocketPushAddress(data).then((res) => {
        return socketPromise(res)
      }).catch(() => {
        return socketPromise({})
      })
    },
    pushSocketLogined: ({commit}, data) => {
      return login.pushSocketLogined(data)
      .then(response => {
        if (response.success) {
          commit(types.PUSH_SOCKET_LOGIN, true)
        }
      }).catch(err => {
        console.log(err)
        // 'message.default_tips'
      })
    }
  },
  mutations: {
    [types.UPDATE_SOCKETID] (state, {socketId}) {
      state.lastSocketId = socketId
    },
    [types.PUSH_SOCKET_LOGIN] (state, data) {
      state.success = data
    },
    [types.UPDATE_SOCKET_PUSH_TOKEN] (state, {token}) {
      state.token = token
    },
    [types.DISCONNECT_SOCKET] (state) {
      if (socket) {
        socket.disconnect()
        socket = null
      }
    }
  }
}
